home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 001-100 / 001-025 / 002 / make / lar.c < prev    next >
C/C++ Source or Header  |  1995-03-17  |  17KB  |  743 lines

  1. /*
  2.  * Lar - LAR format library file maintainer
  3.  * by Stephen C. Hemminger
  4.  *    linus!sch    or    sch@Mitre-Bedford
  5.  *
  6.  * Heavily hacked for MS-DOS by Eric C. Brown
  7.  *      utah-cs!brownc    or    brownc@utah-cs
  8.  *
  9.  *  Usage: lar key library [files] ...
  10.  *
  11.  *  Key functions are:
  12.  *    u - Update, add files to library
  13.  *    t - Table of contents
  14.  *    e - Extract files from library
  15.  *      a - extract All files from library
  16.  *    p - Print files in library
  17.  *    d - Delete files in library
  18.  *    r - Reorganize library
  19.  *  Other keys:
  20.  *    v - Verbose
  21.  *
  22.  *  This program is public domain software, no warranty intended or
  23.  *  implied.
  24.  *
  25.  *  DESCRPTION
  26.  *    Lar is a MS-DOS program to manipulate program libraries.
  27.  *    The primary use of lar is to combine several files together
  28.  *    to reduce disk space used.
  29.  *    Lar maintains the date and time of files in the library, so
  30.  *    that Make can extract the date/time for rebuilding a file.
  31.  *    When files are restored, the file has the original date/time
  32.  *    rather than the date/time when the file was extracted.
  33.  *     The original CP/M library program LU is the product
  34.  *     of Gary P. Novosielski. 
  35.  *
  36.  *  PORTABILITY
  37.  *     The code is modeled after the Software tools archive program,
  38.  *     and is setup for Version 7 Unix.  It does not make any assumptions
  39.  *     about byte ordering, explict and's and shift's are used.
  40.  *     If you have a dumber C compiler, you may have to recode new features
  41.  *     like structure assignment, typedef's and enumerated types.
  42.  *
  43.  *  * Unix is a trademark of Bell Labs.
  44.  *  ** CP/M is a trademark of Digital Research.
  45.  */
  46. #include "lar.h"
  47.  
  48. /* Globals */
  49. char   *fname[MAXFILES];
  50. bool ftouched[MAXFILES];
  51.  
  52. struct ludir ldir[MAXFILES];
  53. int     errcnt, nfiles, nslots;
  54. bool    verbose = false;
  55.  
  56. char   *getname(), *malloc(), *fgets();
  57. long    fcopy(), lseek(), rlwtol();
  58. int    update(), reorg(), table(), extract(), print(), delete(), getall();
  59.  
  60. typedef int (*PFI)();
  61.  
  62. main (argc, argv)
  63. int    argc;
  64. char  **argv;
  65. {
  66.     register char *flagp;
  67.     char   *aname;            /* name of library file */
  68.     PFI function = (PFI) NULL;    /* function to do on library */
  69.     /* set the function to be performed, but detect conflicts */
  70. #define setfunc(val)    if(function != (PFI) NULL) conflict(); else function = val
  71.  
  72.     if (argc < 3)
  73.     help ();
  74.  
  75.     aname = argv[2];
  76.     filenames (argc, argv);
  77.  
  78.     for(flagp = argv[1]; *flagp; flagp++)
  79.     switch (*flagp) {
  80.         case 'u': 
  81.             setfunc(update);
  82.             break;
  83.         case 't': 
  84.             setfunc(table);
  85.             break;
  86.         case 'e': 
  87.             setfunc(extract);
  88.             break;
  89.         case 'a': 
  90.             setfunc(getall);
  91.             break;
  92.         case 'p': 
  93.             setfunc(print);
  94.             break;
  95.         case 'd': 
  96.             setfunc(delete);
  97.             break;
  98.         case 'r': 
  99.             setfunc(reorg);
  100.             break;
  101.         case 'v':
  102.             verbose = true;
  103.             break;
  104.         default: 
  105.             help ();
  106.         }
  107.  
  108.     if(function == (PFI) NULL) {
  109.        fputs("No function key letter specified\n", stderr);
  110.        help();
  111.     }
  112.  
  113.     (*function)(aname);
  114.     exit(0);
  115. }
  116.  
  117. /* print error message and exit */
  118. help () {
  119. fputs ("Usage: lar {uteapdr}[v] library [files] ...\n", stderr);
  120. fputs ("Functions are:\n\tu - Update, add files to library\n", stderr);
  121. fputs ("\tt - Table of contents\n", stderr);
  122. fputs ("\te - Extract files from library\n", stderr);
  123. fputs ("\ta - extract All files from library\n", stderr);
  124. fputs ("\tp - Print files in library\n", stderr);
  125. fputs ("\td - Delete files in library\n", stderr);
  126. fputs ("\tr - Reorganize library\n", stderr);
  127.  
  128. fputs ("Flags are:\n\tv - Verbose\n", stderr);
  129. exit (1);
  130. }
  131.  
  132. conflict() {
  133. fputs ("Conficting keys\n", stderr);
  134. help();
  135. }
  136.  
  137. /*
  138.  * This ltoa doesn't call in the floating point library:
  139.  *   CI C86 does an sprintf!
  140.  */
  141. ltoa(val, buf)
  142. long val;
  143. register char *buf;
  144. {
  145.     register int i;
  146.     int j;
  147.     char tbuf[20];
  148.  
  149.     if (val == 0) {
  150.         buf[0] = '0';
  151.         buf[1] = '\0';
  152.         return;
  153.     }
  154.  
  155.     i = 19;
  156.     while (val != 0) {
  157.         tbuf[i--] = (val % 10) + '0';
  158.         val /= 10;
  159.     }
  160.  
  161.     i++;
  162.     for (j = 0; i <= 19; i++, j++)
  163.         buf[j] = tbuf[i];
  164.  
  165.     buf[j] = '\0';
  166. }
  167.  
  168. /* Get file names, check for dups, and initialize */
  169. filenames (ac, av)
  170. int ac;
  171. char  **av;
  172. {
  173.     register int i, j=0;
  174.     int k, loop;
  175.     struct ffblk ff;
  176.     bool iswild();
  177.  
  178.     errcnt = 0;
  179.     for (i = 0; i < ac - 3; i++) {
  180.         if (iswild(av[i + 3])) {
  181.             k = findfirst(av[i + 3], &ff, 0);
  182.         while (k == 0) {
  183.                 fname[j] = malloc(strlen(ff.ff_name)+1);
  184.                 if (fname[j] == NULL)
  185.                         error("Out of core..");
  186.             strcpy(fname[j], ff.ff_name);
  187.             for (loop = 0; ff.ff_name[loop] != 0; loop++)
  188.                 fname[j][loop] = tolower(ff.ff_name[loop]);
  189.                 ftouched[j] = false;
  190.                 if (j == MAXFILES)
  191.                     error ("Too many file names.");
  192.                 j++;
  193.                 k = findnext(&ff);
  194.             }                /* while */
  195.         }                /* if-then */
  196.         else {        /* not a wildcard */
  197.             fname[j] = av[i+3];
  198.             ftouched[j] = false;
  199.             if (j == MAXFILES)
  200.                 error ("Too many file names.");
  201.             j++;
  202.         }                /* else */
  203.     }                    /* for */
  204.     checkdups(j);
  205. }
  206.  
  207. bool iswild(str)
  208. register char *str;
  209. {
  210.     while (*str != '\0') {
  211.             if (*str == '*' || *str == '?')
  212.                 return true;
  213.             else str++;
  214.     }
  215.     return false;
  216. }
  217.  
  218. checkdups(i)
  219. register int i;
  220. {
  221.     register int j;
  222.  
  223.     fname[i] = NULL;
  224.     nfiles = i;
  225.     for (i = 0; i < nfiles; i++)
  226.             for (j = i + 1; j < nfiles; j++)
  227.             if (equal (fname[i], fname[j])) {
  228.                 fputs (fname[i], stderr);
  229.                 error (": duplicate file name");
  230.                 }
  231. }    
  232.  
  233. table (lib)
  234. char   *lib;
  235. {
  236.     fildesc lfd;
  237.     register int i;
  238.     register struct ludir *lptr;
  239.     long total, offset, size;
  240.     int active = 0, unused = 0, deleted = 0, k;
  241.     char *uname, buf[20];
  242.  
  243.     if ((lfd = _open (lib, O_RDWR)) == SYS_ERROR)
  244.         cant (lib);
  245.  
  246.     getdir (lfd);
  247.     total = lwtol(ldir[0].l_len);
  248.     if (verbose) {
  249.         puts("Name             Index          Length");
  250.        fputs("Directory                       ", stdout);
  251.         ltoa(total, buf);
  252.         puts(buf);
  253.     }
  254.  
  255.     for (i = 1, lptr = &ldir[1]; i < nslots; i++,lptr++)
  256.         switch(lptr->l_stat) {
  257.         case ACTIVE:
  258.                 active++;
  259.              uname = getname(lptr->l_name, lptr->l_ext);
  260.                 if (filarg (uname))
  261.                     if(verbose) {
  262.                     offset = lwtol(lptr->l_off);
  263.                         size = lwtol(lptr->l_len);
  264.                 fputs(uname, stdout);
  265.                 for (k = 1; k < 18 - strlen(uname); k++)
  266.                    fputc(' ', stdout);
  267.                 ltoa(offset, buf);
  268.                 fputs(buf, stdout);
  269.                 for (k = 1; k < 16 - strlen(buf); k++)
  270.                    fputc(' ', stdout);
  271.                 ltoa(size, buf);
  272.                 puts(buf, stdout);
  273.                 }
  274.                  else
  275.                puts(uname);
  276.             total += lwtol(lptr->l_len);
  277.         break;
  278.     case UNUSED:
  279.         unused++;
  280.         break;
  281.     default:
  282.         deleted++;
  283.     }
  284.     if(verbose) {
  285.         puts("--------------------------------------");
  286.         fputs("Total bytes      ", stdout);
  287.         ltoa(total, buf);
  288.         puts(buf);
  289.         fputs("\nLibrary ", stdout);
  290.         fputs(lib, stdout);
  291.         fputs(" has ", stdout);
  292.         itoa(nslots, buf);
  293.         fputs(buf, stdout);
  294.         fputs(" slots, ", stdout);
  295.         itoa(deleted, buf);
  296.         fputs(buf, stdout);
  297.         fputs(" deleted ", stdout);
  298.         itoa(active, buf);
  299.         fputs(buf, stdout);
  300.         fputs(" active, ", stdout);
  301.         itoa(unused, buf);
  302.         fputs(buf, stdout);
  303.         puts(" unused");
  304.           }
  305.  
  306.     VOID _close (lfd);
  307.     not_found ();
  308. }
  309.  
  310. putdir (f)
  311. fildesc f;
  312. {
  313.  
  314.     lseek(f, 0L, 0);        /* rewind f */
  315.     if (_write (f, (char *) ldir, DSIZE * nslots) != nslots * DSIZE)
  316.     error ("Can't write directory - library may be botched");
  317. }
  318.  
  319. initdir (f)
  320. fildesc f;
  321. {
  322.     register int    i;
  323.     long    numbytes;
  324.     char    line[80];
  325.     static struct ludir blankentry = {
  326.     UNUSED,
  327.     { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' },
  328.     { ' ', ' ', ' ' },
  329.     };
  330.     static struct ludir nameentry = {
  331.     ACTIVE,
  332.     { 'l', 'a', 'r', 'f', 'o', 'r', 'm', 't' },
  333.     { 'a', 'r', 'c' },
  334.     };
  335.  
  336.     for (;;) {
  337.     fputs ("Number of slots to allocate (1-255): ", stdout);
  338.     if (fgets (line, 80, stdin) == NULL)
  339.         error ("Eof when reading input");
  340.     nslots = atoi (line);
  341.     if (nslots < 1)
  342.         puts ("Must have at least one!");
  343.     else if (nslots > MAXFILES)
  344.         puts ("Too many slots");
  345.     else
  346.         break;
  347.     }
  348.  
  349.     numbytes = nslots * DSIZE;
  350.  
  351.     for (i = 1; i < nslots; i++)
  352.     ldir[i] = blankentry;
  353.     ldir[0] = nameentry;
  354.     ltolw (ldir[0].l_len, numbytes);
  355.     ltolw (ldir[0].l_datetime, -1L);    /* make funny date field */
  356.  
  357.     putdir (f);
  358. }
  359.  
  360. putname (cpmname, unixname)
  361. char   *cpmname, *unixname;
  362. {
  363.     register char  *p1, *p2;
  364.  
  365.     for (p1 = unixname, p2 = cpmname; *p1; p1++, p2++) {
  366.     while (*p1 == '.') {
  367.         p2 = cpmname + 8;
  368.         p1++;
  369.     }
  370.     if (p2 - cpmname < 11)
  371.         *p2 = islower(*p1) ? toupper(*p1) : *p1;
  372.     else {
  373.         fputs (unixname, stderr);
  374.         fputs (": name truncated\n", stderr);
  375.         break;
  376.     }
  377.     }
  378.     while (p2 - cpmname < 11)
  379.     *p2++ = ' ';
  380. }
  381.  
  382. /* filarg - check if name matches argument list */
  383. filarg (name)
  384. char   *name;
  385. {
  386.     register int    i;
  387.  
  388.     if (nfiles <= 0)
  389.     return 1;
  390.  
  391.     for (i = 0; i < nfiles; i++)
  392.     if (equal (name, fname[i])) {
  393.         ftouched[i] = true;
  394.         return 1;
  395.     }
  396.  
  397.     return 0;
  398. }
  399.  
  400. not_found () {
  401.     register int    i;
  402.  
  403.     for (i = 0; i < nfiles; i++)
  404.     if (!ftouched[i]) {
  405.         fputs(fname[i], stderr);
  406.         fputs(": not in library.\n", stderr);
  407.         errcnt++;
  408.     }
  409. }
  410.  
  411. extract(name)
  412. char *name;
  413. {
  414.     getfiles(name, false);
  415. }
  416.  
  417. print(name)
  418. char *name;
  419. {
  420.     getfiles(name, true);
  421. }
  422.  
  423. getall (libname)
  424. char   *libname;
  425. {
  426.     fildesc lfd, ofd;
  427.     register int    i;
  428.     register struct ludir *lptr;
  429.     union timer timeunion;
  430.     extern int errno;
  431.     char   *unixname;
  432.  
  433.     if ((lfd = _open (libname, O_RDWR)) == SYS_ERROR)
  434.     cant (libname);
  435.  
  436.     getdir (lfd);
  437.  
  438.     for (i = 1, lptr = &ldir[1]; i < nslots; i++, lptr++) {
  439.     if(lptr->l_stat != ACTIVE)
  440.         continue;
  441.     unixname = getname (lptr->l_name, lptr->l_ext);
  442.     fputs(unixname, stderr);
  443.     ofd = _creat(unixname, 0);
  444.     if (ofd == SYS_ERROR) {
  445.         fputs ("  - can't create", stderr);
  446.         errcnt++;
  447.     }
  448.     else {
  449.         VOID lseek (lfd, (long) lwtol (lptr->l_off), 0);
  450.         acopy (lfd, ofd, lwtol (lptr->l_len));
  451.         timeunion.realtime = lwtol(lptr->l_datetime);
  452.             VOID setftime(ofd, &(timeunion.ftimep));
  453.         VOID _close (ofd);
  454.     }
  455.     putc('\n', stderr);
  456.     }
  457.     VOID _close (lfd);
  458.     not_found ();
  459. }
  460.  
  461. getfiles (name, pflag)
  462. char   *name;
  463. bool    pflag;
  464. {
  465.     fildesc lfd, ofd;
  466.     register int    i;
  467.     register struct ludir *lptr;
  468.     union timer timeunion;
  469.     extern int errno;
  470.     char   *unixname;
  471.  
  472.     if ((lfd = _open (name, O_RDWR)) == SYS_ERROR)
  473.     cant (name);
  474.  
  475.     ofd = pflag ? fileno(stdout) : SYS_ERROR;
  476.     getdir (lfd);
  477.  
  478.     for (i = 1, lptr = &ldir[1]; i < nslots; i++, lptr++) {
  479.     if(lptr->l_stat != ACTIVE)
  480.         continue;
  481.     unixname = getname (lptr->l_name, lptr->l_ext);
  482.     if (!filarg (unixname))
  483.         continue;
  484.     fputs(unixname, stderr);
  485.     if (ofd != fileno(stdout))
  486.         ofd = _creat(unixname, 0);
  487.     if (ofd == SYS_ERROR) {
  488.         fputs ("  - can't create", stderr);
  489.         errcnt++;
  490.     }
  491.     else {
  492.         VOID lseek (lfd, (long) lwtol (lptr->l_off), 0);
  493.         acopy (lfd, ofd, lwtol (lptr->l_len));
  494.         timeunion.realtime = lwtol(lptr->l_datetime);
  495.         if (ofd != fileno(stdout)) {
  496.                 VOID setftime(ofd, &(timeunion.ftimep));
  497.         VOID _close (ofd);
  498.         }
  499.     }
  500.     putc('\n', stderr);
  501.     }
  502.     VOID _close (lfd);
  503.     not_found ();
  504. }
  505.  
  506. acopy (fdi, fdo, nbytes)        /* copy nbytes from fdi to fdo */
  507. fildesc fdi, fdo;
  508. long nbytes;
  509. {
  510.     register int btr, retval;
  511.     char blockbuf[BLOCK];
  512.     
  513.     for (btr = (nbytes > BLOCK) ? BLOCK : (int) nbytes; btr > 0; 
  514.          nbytes -= BLOCK, btr = (nbytes > BLOCK) ? BLOCK : (int) nbytes)  {
  515.         if ((retval = _read(fdi, blockbuf, btr)) != btr) {
  516.         if( retval == 0 ) {
  517.         error("Premature EOF\n");
  518.          }
  519.          if( retval == SYS_ERROR)
  520.             error ("Can't read");
  521.     }
  522.     if ((retval = _write(fdo, blockbuf, btr)) != btr) {
  523.          if( retval == SYS_ERROR )
  524.             error ("Write Error");
  525.     }
  526.     }
  527. }
  528.  
  529. update (name)
  530. char   *name;
  531. {
  532.     fildesc lfd;
  533.     register int    i;
  534.  
  535.     if ((lfd = _open(name, O_RDWR)) == SYS_ERROR) {
  536.     if ((lfd = _creat (name, 0)) == SYS_ERROR) {
  537.         cant (name);
  538.     }
  539.     else 
  540.         initdir (lfd);
  541.     }
  542.     else
  543.     getdir (lfd);        /* read old directory */
  544.  
  545.     if(verbose)
  546.         fputs ("Updating files:\n", stderr);
  547.     for (i = 0; i < nfiles; i++)
  548.     addfil (fname[i], lfd);
  549.     if (errcnt == 0)
  550.     putdir (lfd);
  551.     else
  552.     fputs("fatal errors - library not changed\n", stderr);
  553.     VOID _close (lfd);
  554. }
  555.  
  556. addfil (name, lfd)
  557. char   *name;
  558. fildesc lfd;
  559. {
  560.     fildesc ifd;
  561.     register int i;
  562.     register struct ludir *lptr;
  563.     long byteoffs, numbytes;
  564.     union timer timeunion;
  565.  
  566.     if ((ifd = _open(name, O_RDWR)) == SYS_ERROR) {
  567.         fputs("LAR: can't find ", stderr);
  568.     fputs(name, stderr);
  569.     fputs(" to add\n", stderr);
  570.     errcnt++;
  571.     return;
  572.     }
  573.     if(verbose) {
  574.     fputs(name, stderr);
  575.     fputs("\n", stderr);
  576.     }
  577.     for (i = 1, lptr = ldir+1; i < nslots; i++, lptr++) {
  578.     if (equal( getname (lptr->l_name, lptr->l_ext), name) ) /* update */
  579.         break;
  580.     if (lptr->l_stat != ACTIVE)
  581.         break;
  582.     }
  583.     if (i >= nslots) {
  584.     fputs(name, stderr);
  585.     fputs(": can't add library is full\n",stderr);
  586.     errcnt++;
  587.     return;
  588.     }
  589.  
  590.     lptr->l_stat = ACTIVE;
  591.     putname (lptr->l_name, name);
  592.     byteoffs = lseek(lfd, 0L, 2);    /* append to end; return byte offset */
  593.  
  594.     ltolw (lptr->l_off, byteoffs);
  595.     numbytes = fcopy (ifd, lfd);
  596.     ltolw (lptr->l_len, numbytes);
  597.     getftime(ifd, &(timeunion.ftimep));
  598.     ltolw (lptr->l_datetime, timeunion.realtime);
  599.     VOID _close (ifd);
  600. }
  601.  
  602. long fcopy (ifd, ofd)        /*  copy file ifd (file) to ofd (library) */
  603. fildesc ifd, ofd;
  604. {
  605.     long total = 0L;
  606.     register int n;
  607.     char blockbuf[BLOCK];
  608.  
  609.     while ( (n = _read(ifd, blockbuf, BLOCK)) > 0) {
  610.     if (_write(ofd, blockbuf, n) != n)
  611.         error("write error");
  612.     total += (long) n;
  613.     }
  614.     return total;
  615. }
  616.  
  617. delete (lname)
  618. char   *lname;
  619. {
  620.     fildesc f;
  621.     register int    i;
  622.     register struct ludir *lptr;
  623.  
  624.     if ((f = _open(lname, O_RDWR)) == SYS_ERROR)
  625.     cant (lname);
  626.  
  627.     if (nfiles <= 0)
  628.     error("delete by name only");
  629.  
  630.     getdir (f);
  631.     for (i = 0, lptr = ldir; i < nslots; i++, lptr++) {
  632.     if (!filarg ( getname (lptr->l_name, lptr->l_ext)))
  633.         continue;
  634.     lptr->l_stat = DELETED;
  635.     }
  636.  
  637.     not_found();
  638.     if (errcnt > 0)
  639.     fputs ("errors - library not updated\n", stderr);
  640.     else
  641.     putdir (f);
  642.     VOID _close (f);
  643. }
  644.  
  645. reorg (name)
  646. char  *name;
  647. {
  648.     fildesc olib, nlib;
  649.     int oldsize, k;
  650.     register struct ludir *optr;
  651.     register int i, j;
  652.     struct ludir odir[MAXFILES], *nptr;
  653.     char tmpname[80], buf[10];
  654.     char *mktemp();
  655.  
  656.     strcpy(tmpname, mktemp("libXXXXXX"));
  657.  
  658.     if( (olib = _open(name, O_RDWR)) == SYS_ERROR)
  659.     cant(name);
  660.  
  661.     if( (nlib = _creat(tmpname, 0)) == SYS_ERROR)
  662.     cant(tmpname);
  663.  
  664.     getdir(olib);
  665.     fputs("Old library has ", stdout);
  666.     itoa(oldsize = nslots, buf);
  667.     fputs(buf, stdout);
  668.     puts(" slots.");
  669. /* copy ldir into odir */
  670.     for(i = 0, optr = ldir, nptr = odir ; i < nslots ; i++, optr++, nptr++)
  671.     movmem((char *) optr, (char *) nptr, sizeof(struct ludir));
  672. /* reinit ldir */
  673.     initdir(nlib);
  674.     errcnt = 0;
  675.  
  676. /* copy odir's files into ldir */
  677.     for (i = j = 1, optr = odir+1; i < oldsize; i++, optr++) {
  678.     if( optr->l_stat == ACTIVE ) {
  679.         if(verbose) {
  680.             fputs("Copying: ", stderr);
  681.         for (k = 0; k < 8; k++) 
  682.             fputc(optr->l_name[k], stderr);
  683.         fputc('.', stderr);
  684.         for (k = 0; k < 3; k++)
  685.             fputc(optr->l_ext[k], stderr);
  686.         fputc('\n', stderr);
  687.         }
  688.         copyentry( optr, olib,  &ldir[j], nlib);
  689.         if (++j >= nslots) {
  690.         errcnt++;
  691.         fputs("Not enough room in new library\n", stderr);
  692.         break;
  693.         }
  694.         }
  695.     }
  696.  
  697.     VOID _close(olib);
  698.     putdir(nlib);
  699.     VOID _close (nlib);
  700.  
  701.     if(errcnt == 0) {
  702.     if (unlink(name) < 0 || rename(tmpname, name) < 0) {
  703.         cant(name);
  704.         exit(1);
  705.     }
  706.     }
  707.     else
  708.     fputs("Errors, library not updated\n", stderr);
  709.     VOID unlink(tmpname);
  710. }
  711.  
  712. copyentry( old, of, new, nf )
  713. struct ludir *old, *new;
  714. fildesc of, nf;
  715. {
  716.     long byteoffs, numbytes;
  717.     register int btr;
  718.     char blockbuf[BLOCK];
  719.     
  720.     new->l_stat = ACTIVE;
  721.     movmem(old->l_name, new->l_name, 8);        /* copy name */
  722.     movmem(old->l_ext, new->l_ext, 3);            /* copy extension */
  723.     numbytes = lwtol(old->l_datetime);            /* copy date & time */
  724.     ltolw(new->l_datetime, numbytes);
  725.     VOID lseek(of, (long) lwtol(old->l_off), 0);
  726.     byteoffs = lseek(nf, 0L, 2);    /* append to end; return new pos. */
  727.  
  728.     ltolw (new->l_off, byteoffs);
  729.     numbytes = lwtol(old->l_len);
  730.     ltolw (new->l_len, numbytes);
  731.  
  732.     for (btr = (numbytes > BLOCK) ? BLOCK : (int) numbytes; btr > 0; 
  733.          numbytes -= BLOCK, btr = (numbytes > BLOCK) ? BLOCK : (int) numbytes
  734.         )  {
  735.         if (_read(of, blockbuf, btr) != btr) {
  736.         error ("Read Error in CopyEntry");
  737.     }
  738.     if (_write(nf, blockbuf, btr) != btr) {
  739.         error ("Write Error in CopyEntry");
  740.     }
  741.     }
  742. }
  743.